import socket
import numpy as np
import threading
import socket
import threading
import time
from flask import Flask, Response
import cv2
import numpy as np
import queue
import struct



HOST = '0.0.0.0'
PORT = 8869
HEADER_SIZE = 4  # 4字节包头表示数据长度
DATA_SIZE = 6 * 4  # 6个float32 = 24字节

clients = {}
client_lock = threading.Lock()

def handle_client(conn, addr):
    global clients
    print(f"Connected: {addr}")
    
    # 接收客户端身份标识
    identity = conn.recv(1).decode()
    with client_lock:
        clients[identity] = conn
    
    print(f"Registered as: {identity}")
    
    # 转发数据
    try:
        while True:
            # 读取包头
            header = conn.recv(HEADER_SIZE)
            if not header: break
            
            # 解析数据长度
            data_len = int.from_bytes(header, 'big')
            data = b''
            while len(data) < data_len:
                packet = conn.recv(data_len - len(data))
                if not packet: break
                data += packet
            
            if len(data) != data_len:
                break
            
            # 转发给目标客户端
            target = '2' if identity == '1' else '1'
            with client_lock:
                target_conn = clients.get(target)
                if target_conn:
                    try:
                        target_conn.sendall(header + data)
                    except:
                        pass
    finally:
        with client_lock:
            if identity in clients:
                del clients[identity]
        conn.close()
        print(f"Disconnected: {addr}")

def main():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind((HOST, PORT))
        s.listen()
        print(f"Server listening on {HOST}:{PORT}")
        
        while True:
            conn, addr = s.accept()
            threading.Thread(target=handle_client, args=(conn, addr)).start()


app = Flask(__name__)

# 双缓冲队列
frame_queue = queue.Queue(maxsize=2)
latest_frame = None

def socket_server():
    global latest_frame
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(('0.0.0.0', 8870))
    server_socket.listen(5)
    print("Socket服务器启动，等待客户端连接...")
    
    conn, addr = server_socket.accept()
    print(f"客户端已连接: {addr}")
    
    try:
        while True:
            # 接收帧大小信息
            size_data = conn.recv(4)
            if not size_data:
                break
            frame_size = struct.unpack('!I', size_data)[0]
            
            # 接收帧数据
            frame_data = b''
            while len(frame_data) < frame_size:
                packet = conn.recv(frame_size - len(frame_data))
                if not packet:
                    break
                frame_data += packet
            
            # 解码帧
            frame = cv2.imdecode(np.frombuffer(frame_data, dtype=np.uint8), cv2.IMREAD_COLOR)
            
            # 更新帧队列（双缓冲）
            if not frame_queue.full():
                frame_queue.put(frame)
            else:
                # 队列满时丢弃旧帧，保留最新
                try:
                    frame_queue.get_nowait()
                except queue.Empty:
                    pass
                frame_queue.put(frame)
            
            # 更新最新帧（用于网页显示）
            latest_frame = frame
            
    except Exception as e:
        print(f"连接错误: {e}")
    finally:
        conn.close()
        server_socket.close()

def generate_frames():
    global latest_frame
    while True:
        if latest_frame is not None:
            # 转换为JPEG格式
            ret, buffer = cv2.imencode('.jpg', latest_frame)
            frame = buffer.tobytes()
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
        else:
            # 无帧时发送空白图像
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + 
                   open('blank.jpg', 'rb').read() + b'\r\n')
        time.sleep(0.05)  # 控制帧率(20fps)

@app.route('/video_feed')
def video_feed():
    return Response(generate_frames(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/')
def index():
    return """
    <html>
    <head>
        <title>实时视频监控</title>
    </head>
    <body>
        <h1>实时摄像头</h1>
        <img src="/video_feed" width="640">
    </body>
    </html>
    """


if __name__ == "__main__":
    # 启动Socket服务器线程
    socket_thread = threading.Thread(target=socket_server, daemon=True)
    socket_thread.start()

    main_thread = threading.Thread(target=main, daemon=True)
    main_thread.start()
    
    # 启动Flask服务器
    app.run(host='0.0.0.0', port=8868, threaded=True)

